package org.pfc.porlapatilla.controllers;

import java.util.List;

import org.pfc.porlapatilla.DTO.ResultDTO;
import org.pfc.porlapatilla.DTO.UserDTO;
import org.pfc.porlapatilla.model.User;
import org.pfc.porlapatilla.model.UserCredentials;
import org.pfc.porlapatilla.services.UserService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

/**
 * This controller manages requests related to users.
 * 
 * @author jorgepolobermudez
 * 
 */
@Controller
@RequestMapping("/users")
public class UserController {

    private static final Logger logger = LoggerFactory
	    .getLogger(UserController.class);

    /**
     * The UserService instance.
     */
    @Autowired
    private UserService userService;

    /**
     * Find all stored users.
     * 
     * @param page
     *            Page number.
     * @param size
     *            Size of page.
     * @return The list of <strong>size</strong> users in the page
     *         <strong>page</strong>.
     */
    @RequestMapping(method = RequestMethod.GET)
    public @ResponseBody
    List<User> getUsers(
	    @RequestParam(value = "page", required = false) Integer page,
	    @RequestParam(value = "size", required = false) Integer size) {

	if (page == null || size == null) {
	    logger.info("Retrieving all users");
	    return userService.findAll();
	}

	logger.info("Retrieving all users: page {" + page + "}, size {" + size
		+ "}");
	return userService.findAll(page, size);
    }

    /**
     * Find stored user by id.
     * 
     * @param id
     *            The user id.
     * @return The found user.
     */
    /*@RequestMapping(value = "/{id}", method = RequestMethod.GET)
    public @ResponseBody
    User getUserById(@PathVariable String id) {
	logger.info("Retrieving user by id + [" + id + "]");
	return userService.findById(id);
    }*/

    /**
     * Find stored user by email.
     * 
     * @param email
     *            The user email.
     * @return The found user.
     */
    @RequestMapping(value = "/email", method = RequestMethod.GET)
    public @ResponseBody
    User getUserByEmail(
	    @RequestParam(value = "param", required = true) String email) {
	logger.info("Retrieving user by email + [" + email + "]");
	return userService.findByEmail(email);
    }

    /**
     * Create a new <strong>user</strong>
     * 
     * @param userDTO
     *            The new <strong>user</strong> to create
     * @return The new <strong>user</strong> id
     */
    @RequestMapping(value = "/create", method = RequestMethod.POST)
    public @ResponseBody
    ResultDTO addUser(@RequestBody UserDTO userDTO) {
	logger.info("Creating new user");

	User user;
	user = userService.findByEmail(userDTO.getEmail());
	if (user != null) {
	    // This email is being used by other user
	    return new ResultDTO(ResultDTO.RESULT_ERROR,
		    ResultDTO.RESULT_ERROR_EMAIL);
	}

	user = userService.findByNick(userDTO.getNick());
	if (user != null) {
	    // This nick is being used by other user
	    return new ResultDTO(ResultDTO.RESULT_ERROR,
		    ResultDTO.RESULT_ERROR_USER);
	}

	String userId = userService.store(userDTO);
	if (userId == null) {
	    // Error occurred creating the new user
	    return new ResultDTO(ResultDTO.RESULT_ERROR,
		    ResultDTO.RESULT_ERROR_STORE);
	}

	// User created
	return new ResultDTO(ResultDTO.RESULT_OK, null);
    }

    /**
     * Update an <strong>user</strong>
     * 
     * @param user
     *            The <strong>user</strong> to update
     * @return "OK" if the update is successfully, "ERROR" if not.
     */
    @RequestMapping(value = "/update", method = RequestMethod.POST)
    public @ResponseBody
    ResultDTO updateUser(@RequestBody UserDTO userDTO) {

	boolean result = userService.update(userDTO);
	if (result) {
	    return new ResultDTO(ResultDTO.RESULT_OK, null);
	} else {
	    return new ResultDTO(ResultDTO.RESULT_ERROR,
		    ResultDTO.RESULT_ERROR_STORE);
	}
    }

    /**
     * Login an <strong>user</strong>
     * 
     * @param credentials
     *            The <strong>user</strong> credentials.
     * @return 
     */
    @RequestMapping(value = "/login", method = RequestMethod.POST)
    public @ResponseBody
    ResultDTO loginUser(@RequestBody UserCredentials credentials) {
	User user = userService.findByNick(credentials.getUser());
	if (user == null) {
	    // Wrong user
	    return new ResultDTO(ResultDTO.RESULT_ERROR,
		    ResultDTO.RESULT_ERROR_USER);
	}

	if (!credentials.getPass().equals(user.getPassword())) {
	    // Wrong password
	    return new ResultDTO(ResultDTO.RESULT_ERROR,
		    ResultDTO.RESULT_ERROR_PASS);
	}

	// Login success
	return new ResultDTO(ResultDTO.RESULT_OK, null);
    }

    /*
     * @RequestMapping(value = "/login", method = RequestMethod.GET) public
     * 
     * @ResponseBody UserCredentials loginUser() { UserCredentials credentials =
     * new UserCredentials("jorgepb","jorgepb"); return credentials; }
     */

    /**
     * Get user profile info
     * 
     * @param nick
     *            The user nick
     * @return The user profile info
     */
    @RequestMapping(value = "/{nick}", method = RequestMethod.GET)
    public @ResponseBody
    UserDTO getUserProfile(@PathVariable String nick) {
	logger.info("Retrieving user by nick");
	UserDTO userDTO = userService.getUserProfile(nick);
	return userDTO;
    }

    /**
     * Changes user password
     * @param userDTO
     * @param nick The user nick
     * @return 
     */
    @RequestMapping(value = "/{nick}/changePassword", method = RequestMethod.POST)
    public @ResponseBody
    ResultDTO changePassword(@RequestBody UserDTO userDTO,
	    @PathVariable String nick) {

	boolean passwordChanged = userService.changeUserPassword(userDTO);
	if (passwordChanged) {
	    return new ResultDTO(ResultDTO.RESULT_OK, null);
	} else {
	    return new ResultDTO(ResultDTO.RESULT_ERROR,
		    ResultDTO.RESULT_ERROR_STORE);
	}
    }
}
